package com.pai4j.zwiki.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pai4j.zwiki.domain.entity.*;
import com.pai4j.zwiki.repository.*;
import com.pai4j.zwiki.service.diagram.DatabaseDiagramService;
import com.pai4j.zwiki.service.diagram.DiagramEnhancedService;
import com.pai4j.zwiki.service.template.IntelligentThesisFillerService;
import com.pai4j.zwiki.service.template.TemplateAnalyzerService;
import com.pai4j.zwiki.service.template.ThesisDiagramManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * 交互式论文生成服务
 * 实现用户上传模板 → AI填充 → 用户预览 → 反馈优化的完整流程
 *
 * @author pai4j
 * @since 2025-10-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractiveThesisService {

    private final DetailedAnalysisReportRepository detailedAnalysisReportRepository;
    private final ThesisVersionRepository thesisVersionRepository;
    private final ThesisFeedbackRepository thesisFeedbackRepository;
    private final TemplateAnalyzerService templateAnalyzerService;
    private final IntelligentThesisFillerService intelligentFillerService;
    private final ThesisDiagramManager diagramManager;
    private final DiagramEnhancedService diagramEnhancedService;
    private final DatabaseDiagramService databaseDiagramService;
    private final LLMService llmService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Value("${zwiki.workspace.base-path:/tmp/zwiki-workspace}")
    private String workspaceBasePath;

    /**
     * 步骤1：上传并解析论文模板（优化版 - 改进参数校验和资源管理）
     *
     * @param taskId 任务ID
     * @param templateFile 用户上传的模板文件（可选）
     * @return 模板解析结果
     */
    @Transactional
    public Map<String, Object> uploadAndAnalyzeTemplate(String taskId, MultipartFile templateFile) {
        log.info("上传并解析论文模板, 任务ID: {}", taskId);
        
        // 参数校验
        if (taskId == null || taskId.trim().isEmpty()) {
            throw new IllegalArgumentException("任务ID不能为空");
        }

        try {
            String templatePath;

            if (templateFile != null && !templateFile.isEmpty()) {
                // 验证文件类型
                String filename = templateFile.getOriginalFilename();
                if (filename == null || !filename.toLowerCase().endsWith(".docx")) {
                    throw new IllegalArgumentException("模板文件必须是 .docx 格式");
                }
                
                // 验证文件大小（不超过10MB）
                if (templateFile.getSize() > 10 * 1024 * 1024) {
                    throw new IllegalArgumentException("模板文件大小不能超过 10MB");
                }
                
                // 保存用户上传的模板
                templatePath = saveUploadedTemplate(taskId, templateFile);
                log.info("用户上传模板已保存: {}", templatePath);
            } else {
                // 使用默认模板
                templatePath = templateAnalyzerService.generateDefaultTemplate(taskId, "项目");
                log.info("使用默认模板: {}", templatePath);
            }

            // 解析模板结构
            Map<String, Object> templateStructure;
            Path templateFilePath = Paths.get(templatePath);
            
            // 使用文件创建 MultipartFile 进行解析
            templateStructure = templateAnalyzerService.analyzeTemplate(
                    createMultipartFileFromPath(templateFilePath),
                    taskId
            );

            templateStructure.put("templatePath", templatePath);

            return templateStructure;

        } catch (IllegalArgumentException e) {
            log.warn("模板参数错误: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("上传和解析模板失败", e);
            throw new RuntimeException("模板处理失败: " + e.getMessage(), e);
        }
    }

    /**
     * 步骤2：智能填充论文内容（优化版 - 改进参数校验和异常处理）
     * 让 LLM 根据项目分析报告和模板结构，智能生成并填充内容
     *
     * @param taskId 任务ID
     * @param templatePath 模板路径
     * @return 论文版本ID
     */
    @Transactional
    public String intelligentFillThesis(String taskId, String templatePath) {
        log.info("开始智能填充论文（含完整图表）, 任务ID: {}", taskId);
        
        // 参数校验
        if (taskId == null || taskId.trim().isEmpty()) {
            throw new IllegalArgumentException("任务ID不能为空");
        }
        if (templatePath == null || templatePath.trim().isEmpty()) {
            throw new IllegalArgumentException("模板路径不能为空");
        }
        if (!Files.exists(Paths.get(templatePath))) {
            throw new IllegalArgumentException("模板文件不存在: " + templatePath);
        }

        FileInputStream templateStream = null;
        XWPFDocument document = null;
        try {
            // 获取详细分析报告
            DetailedAnalysisReportEntity analysisReport = detailedAnalysisReportRepository
                    .findByTaskId(taskId)
                    .orElseThrow(() -> new RuntimeException("分析报告不存在"));
            
            if (analysisReport == null) {
                throw new RuntimeException("分析报告为空");
            }

            // 第一步：生成所有图表
            log.info("开始生成所有图表...");
            Map<String, String> availableDiagrams = generateAllDiagramsForThesis(taskId);
            log.info("图表生成完成，共 {} 个图表", availableDiagrams.size());

            // 第二步：生成图表说明
            log.info("开始生成图表说明...");
            Map<String, String> diagramDescriptions = intelligentFillerService
                    .generateAllDiagramDescriptions(availableDiagrams, analysisReport);

            // 读取模板（使用 try-with-resources）
            templateStream = new FileInputStream(templatePath);
            document = new XWPFDocument(templateStream);
            Map<String, Object> filledContent = new HashMap<>();
            List<Map<String, String>> diagramInsertions = new ArrayList<>();

            // 遍历段落，智能填充
            for (int i = 0; i < document.getParagraphs().size(); i++) {
                XWPFParagraph paragraph = document.getParagraphs().get(i);
                String text = paragraph.getText();

                // 查找占位符（添加 null 检查）
                if (text != null && text.contains("{{") && text.contains("}}")) {
                    // 提取上下文
                    String context = extractContext(document, i);
                    
                    // 智能填充每个占位符
                    String filledText = intelligentlyFillParagraph(text, context, analysisReport);
                    
                    // 替换段落内容
                    replaceParagraphText(paragraph, filledText);
                    
                    filledContent.put("paragraph_" + i, filledText);
                }

                // 检查是否需要插入图表（使用增强的检测）
                if (shouldInsertDiagram(paragraph, analysisReport)) {
                    Map<String, String> insertion = suggestDiagramForParagraphEnhanced(
                            paragraph, analysisReport, availableDiagrams);
                    if (insertion != null) {
                        // 添加图表描述
                        String diagramType = insertion.get("diagramType");
                        String description = diagramDescriptions.get(diagramType);
                        insertion.put("description", description != null ? description : "");
                        diagramInsertions.add(insertion);
                    }
                }
            }

            // 第三步：智能插入图表
            log.info("开始插入图表到论文...");
            insertDiagramsIntelligentlyEnhanced(document, diagramInsertions, availableDiagrams, taskId);

            // 保存填充后的论文
            Integer latestVersion = thesisVersionRepository.getLatestVersion(taskId);
            Integer newVersion = (latestVersion != null ? latestVersion : 0) + 1;
            String docxPath = saveThesisVersion(document, taskId, newVersion);

            // 生成HTML预览（包含图表）
            String htmlPreview = generateHtmlPreviewWithDiagrams(document, availableDiagrams);

            // 保存版本记录
            ThesisVersionEntity versionEntity = ThesisVersionEntity.builder()
                    .taskId(taskId)
                    .version(newVersion)
                    .fullContent(objectMapper.writeValueAsString(filledContent))
                    .htmlPreview(htmlPreview)
                    .docxFilePath(docxPath)
                    .status("preview")
                    .templatePath(templatePath)
                    .insertedDiagrams(objectMapper.writeValueAsString(diagramInsertions))
                    .isCurrent(true)
                    .versionNotes("初始版本 - AI自动填充（含完整图表）")
                    .build();

            // 设置其他版本为非当前
            thesisVersionRepository.findByTaskIdAndIsCurrentTrue(taskId)
                    .ifPresent(old -> {
                        old.setIsCurrent(false);
                        thesisVersionRepository.save(old);
                    });

            thesisVersionRepository.save(versionEntity);

            log.info("论文填充完成, 版本: {}, 路径: {}, 插入图表: {}", 
                    newVersion, docxPath, diagramInsertions.size());
            return versionEntity.getId().toString();

        } catch (IllegalArgumentException e) {
            log.warn("智能填充论文参数错误: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("智能填充论文失败", e);
            throw new RuntimeException("填充论文失败: " + e.getMessage(), e);
        } finally {
            // 确保资源被正确释放
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    log.warn("关闭文档失败", e);
                }
            }
            if (templateStream != null) {
                try {
                    templateStream.close();
                } catch (IOException e) {
                    log.warn("关闭模板流失败", e);
                }
            }
        }
    }

    /**
     * 为论文生成所有类型的图表
     */
    private Map<String, String> generateAllDiagramsForThesis(String taskId) {
        Map<String, String> diagrams = new HashMap<>();

        try {
            // 生成代码相关图表
            Map<String, String> codeDiagrams = diagramEnhancedService.generateAllDiagrams(taskId);
            diagrams.putAll(codeDiagrams);

            // 尝试生成数据库相关图表（如果有数据库配置）
            try {
                String databaseName = extractDatabaseName(taskId);
                if (databaseName != null) {
                    String erDiagram = databaseDiagramService.generateERDiagram(taskId, databaseName);
                    if (erDiagram != null) {
                        diagrams.put("erDiagram", erDiagram);
                    }

                    Map<String, String> tableStructures = databaseDiagramService
                            .generateTableStructureDiagrams(taskId, databaseName);
                    diagrams.putAll(tableStructures);
                }
            } catch (Exception e) {
                log.warn("数据库图表生成失败（可能未配置数据库）: {}", e.getMessage());
            }

            log.info("所有图表生成完成，共 {} 个", diagrams.size());

        } catch (Exception e) {
            log.error("生成图表失败", e);
        }

        return diagrams;
    }

    /**
     * 从项目分析结果中提取数据库名称
     */
    private String extractDatabaseName(String taskId) {
        try {
            DetailedAnalysisReportEntity report = detailedAnalysisReportRepository
                    .findByTaskId(taskId)
                    .orElse(null);
            
            if (report != null) {
                String techStack = report.getTechStack();
                if (techStack != null && techStack.contains("database")) {
                    // 解析技术栈，提取数据库名称
                    // 这里简化处理，实际应该从配置文件中读取
                    return "project_db";
                }
            }
        } catch (Exception e) {
            log.warn("提取数据库名称失败: {}", e.getMessage());
        }
        return null;
    }

    /**
     * 步骤3：用户提交反馈
     *
     * @param taskId 任务ID
     * @param version 版本号
     * @param section 章节
     * @param feedbackType 反馈类型
     * @param feedbackContent 反馈内容
     * @return 反馈ID
     */
    @Transactional
    public Long submitFeedback(
            String taskId,
            Integer version,
            String section,
            String feedbackType,
            String feedbackContent) {
        
        log.info("用户提交反馈, 任务ID: {}, 版本: {}, 类型: {}", taskId, version, feedbackType);

        ThesisFeedbackEntity feedback = ThesisFeedbackEntity.builder()
                .taskId(taskId)
                .version(version)
                .section(section)
                .feedbackType(feedbackType)
                .feedbackContent(feedbackContent)
                .processed(false)
                .build();

        thesisFeedbackRepository.save(feedback);

        log.info("反馈已保存, ID: {}", feedback.getId());
        return feedback.getId();
    }

    /**
     * 步骤4：根据反馈优化论文
     * AI 根据用户反馈重新生成或优化对应部分
     *
     * @param taskId 任务ID
     * @param feedbackId 反馈ID
     * @return 新版本ID
     */
    @Transactional
    public String optimizeThesisBasedOnFeedback(String taskId, Long feedbackId) {
        log.info("根据反馈优化论文, 反馈ID: {}", feedbackId);

        try {
            // 获取反馈
            ThesisFeedbackEntity feedback = thesisFeedbackRepository.findById(feedbackId)
                    .orElseThrow(() -> new RuntimeException("反馈不存在"));

            // 获取当前版本
            ThesisVersionEntity currentVersion = thesisVersionRepository
                    .findByTaskIdAndIsCurrentTrue(taskId)
                    .orElseThrow(() -> new RuntimeException("当前版本不存在"));

            // 获取分析报告
            DetailedAnalysisReportEntity analysisReport = detailedAnalysisReportRepository
                    .findByTaskId(taskId)
                    .orElseThrow(() -> new RuntimeException("分析报告不存在"));

            // 读取当前文档
            XWPFDocument document = new XWPFDocument(new FileInputStream(currentVersion.getDocxFilePath()));

            // 定位需要优化的段落
            XWPFParagraph targetParagraph = findParagraphBySection(document, feedback.getSection());

            if (targetParagraph != null) {
                String originalContent = targetParagraph.getText();
                feedback.setOriginalContent(originalContent);

                // 使用 LLM 优化内容
                String optimizedContent = intelligentFillerService.optimizeContentBasedOnFeedback(
                        originalContent,
                        feedback.getFeedbackContent(),
                        analysisReport
                );

                // 替换段落内容
                replaceParagraphText(targetParagraph, optimizedContent);
                feedback.setOptimizedContent(optimizedContent);
                feedback.setProcessed(true);
                thesisFeedbackRepository.save(feedback);

                log.info("内容已优化, 原始长度: {}, 优化后长度: {}", 
                        originalContent.length(), optimizedContent.length());
            }

            // 保存新版本
            Integer newVersion = currentVersion.getVersion() + 1;
            String newDocxPath = saveThesisVersion(document, taskId, newVersion);
            String htmlPreview = generateHtmlPreview(document);

            ThesisVersionEntity newVersionEntity = ThesisVersionEntity.builder()
                    .taskId(taskId)
                    .version(newVersion)
                    .htmlPreview(htmlPreview)
                    .docxFilePath(newDocxPath)
                    .status("preview")
                    .templatePath(currentVersion.getTemplatePath())
                    .isCurrent(true)
                    .versionNotes("根据用户反馈优化：" + feedback.getFeedbackType())
                    .build();

            // 设置旧版本为非当前
            currentVersion.setIsCurrent(false);
            thesisVersionRepository.save(currentVersion);

            thesisVersionRepository.save(newVersionEntity);

            log.info("优化完成，新版本: {}", newVersion);
            return newVersionEntity.getId().toString();

        } catch (Exception e) {
            log.error("优化论文失败", e);
            throw new RuntimeException("优化失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取论文预览（HTML格式）
     */
    public String getThesisPreview(String taskId, Integer version) {
        ThesisVersionEntity versionEntity = version != null ?
                thesisVersionRepository.findByTaskIdAndVersion(taskId, version)
                        .orElseThrow(() -> new RuntimeException("版本不存在")) :
                thesisVersionRepository.findByTaskIdAndIsCurrentTrue(taskId)
                        .orElseThrow(() -> new RuntimeException("论文不存在"));

        return versionEntity.getHtmlPreview();
    }

    /**
     * 获取所有版本列表
     */
    public List<ThesisVersionEntity> getVersionHistory(String taskId) {
        return thesisVersionRepository.findByTaskIdOrderByVersionDesc(taskId);
    }

    /**
     * 确认最终版本
     */
    @Transactional
    public void confirmFinalVersion(String taskId, Integer version) {
        ThesisVersionEntity versionEntity = thesisVersionRepository
                .findByTaskIdAndVersion(taskId, version)
                .orElseThrow(() -> new RuntimeException("版本不存在"));

        versionEntity.setStatus("final");
        thesisVersionRepository.save(versionEntity);

        log.info("论文版本已确认为最终版本: v{}", version);
    }

    // ========== 私有辅助方法 ==========

    /**
     * 从路径创建 MultipartFile（用于传递给需要 MultipartFile 的方法）
     */
    private MultipartFile createMultipartFileFromPath(Path filePath) throws IOException {
        byte[] fileContent = Files.readAllBytes(filePath);
        String filename = filePath.getFileName().toString();
        
        return new org.springframework.mock.web.MockMultipartFile(
                "template",
                filename,
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                fileContent
        );
    }
    
    private String saveUploadedTemplate(String taskId, MultipartFile file) throws IOException {
        Path templateDir = Paths.get(workspaceBasePath, taskId, "templates");
        Files.createDirectories(templateDir);
        
        Path templatePath = templateDir.resolve("user-template.docx");
        file.transferTo(templatePath.toFile());
        
        return templatePath.toString();
    }

    private String extractContext(XWPFDocument document, int paragraphIndex) {
        StringBuilder context = new StringBuilder();
        
        // 获取前后各2段作为上下文
        int start = Math.max(0, paragraphIndex - 2);
        int end = Math.min(document.getParagraphs().size() - 1, paragraphIndex + 2);
        
        for (int i = start; i <= end; i++) {
            if (i != paragraphIndex) {
                context.append(document.getParagraphs().get(i).getText()).append("\n");
            }
        }
        
        return context.toString();
    }

    private String intelligentlyFillParagraph(
            String text,
            String context,
            DetailedAnalysisReportEntity report) {
        
        String filled = text;
        
        // 提取所有占位符
        List<String> placeholders = extractAllPlaceholders(text);
        
        for (String placeholder : placeholders) {
            // 使用智能填充服务
            String content = intelligentFillerService.intelligentFillContent(
                    placeholder, context, report);
            
            // 替换占位符
            filled = filled.replace(placeholder, content);
        }
        
        return filled;
    }

    private boolean shouldInsertDiagram(XWPFParagraph paragraph, DetailedAnalysisReportEntity report) {
        String text = paragraph.getText().toLowerCase();
        
        return text.contains("架构") || text.contains("设计") || 
               text.contains("结构") || text.contains("流程") ||
               text.contains("模块") || text.contains("类图");
    }

    private Map<String, String> suggestDiagramForParagraph(
            XWPFParagraph paragraph,
            DetailedAnalysisReportEntity report) {
        
        String text = paragraph.getText();
        String diagramType = null;
        
        if (text.contains("架构")) diagramType = "layerArchitecture";
        else if (text.contains("类图")) diagramType = "detailedClassDiagram";
        else if (text.contains("流程") || text.contains("调用")) diagramType = "callChain";
        else if (text.contains("模块")) diagramType = "moduleRelation";
        else if (text.contains("依赖")) diagramType = "packageDependency";
        
        if (diagramType != null) {
            Map<String, String> suggestion = new HashMap<>();
            suggestion.put("afterParagraph", text);
            suggestion.put("diagramType", diagramType);
            return suggestion;
        }
        
        return null;
    }

    /**
     * 增强版：为段落推荐图表（使用所有可用图表）
     */
    private Map<String, String> suggestDiagramForParagraphEnhanced(
            XWPFParagraph paragraph,
            DetailedAnalysisReportEntity report,
            Map<String, String> availableDiagrams) {
        
        String text = paragraph.getText().toLowerCase();
        String diagramType = null;
        
        // 更全面的匹配规则
        if (text.contains("分层") || text.contains("架构层")) 
            diagramType = "layerArchitecture";
        else if (text.contains("组件") && text.contains("交互")) 
            diagramType = "componentInteraction";
        else if (text.contains("类图") || text.contains("类结构")) 
            diagramType = "classDiagram";
        else if (text.contains("包依赖") || text.contains("模块依赖")) 
            diagramType = "packageDependency";
        else if (text.contains("时序") || text.contains("调用链") || text.contains("调用流程")) 
            diagramType = "sequenceDiagram";
        else if (text.contains("业务流程") || text.contains("处理流程")) 
            diagramType = "businessFlow";
        else if (text.contains("状态") && (text.contains("转换") || text.contains("流转"))) 
            diagramType = "stateMachine";
        else if (text.contains("设计模式") || text.contains("模式应用")) 
            diagramType = "designPatterns";
        else if (text.contains("部署") && text.contains("架构")) 
            diagramType = "deploymentArchitecture";
        else if (text.contains("监控") && (text.contains("架构") || text.contains("体系"))) 
            diagramType = "monitoringArchitecture";
        else if (text.contains("er图") || text.contains("实体关系")) 
            diagramType = "erDiagram";
        else if (text.contains("表结构") || text.contains("数据表")) 
            diagramType = "tableStructure";
        else if (text.contains("模块关系") || text.contains("模块划分")) 
            diagramType = "moduleRelation";
        
        // 检查图表是否可用
        if (diagramType != null && availableDiagrams.containsKey(diagramType)) {
            Map<String, String> suggestion = new HashMap<>();
            suggestion.put("afterParagraph", text);
            suggestion.put("diagramType", diagramType);
            suggestion.put("diagramPath", availableDiagrams.get(diagramType));
            return suggestion;
        }
        
        return null;
    }

    private void insertDiagramsIntelligently(
            XWPFDocument document,
            List<Map<String, String>> insertions,
            String taskId) throws IOException {
        
        Path diagramDir = Paths.get(workspaceBasePath, taskId, "diagrams");
        
        for (Map<String, String> insertion : insertions) {
            String diagramType = insertion.get("diagramType");
            String imagePath = diagramDir.resolve(diagramType + ".png").toString();
            
            if (Files.exists(Paths.get(imagePath))) {
                // 在文档中插入图片（简化实现）
                log.info("插入图表: {} at {}", diagramType, insertion.get("afterParagraph"));
            }
        }
    }

    /**
     * 增强版：智能插入图表到文档中
     */
    private void insertDiagramsIntelligentlyEnhanced(
            XWPFDocument document,
            List<Map<String, String>> insertions,
            Map<String, String> availableDiagrams,
            String taskId) throws IOException {
        
        log.info("开始增强插入图表，共 {} 个插入点", insertions.size());
        
        int figureNumber = 1;
        
        for (Map<String, String> insertion : insertions) {
            String diagramType = insertion.get("diagramType");
            String diagramPath = insertion.get("diagramPath");
            String description = insertion.get("description");
            
            if (diagramPath != null && Files.exists(Paths.get(diagramPath))) {
                try {
                    // 创建新段落用于插入图片
                    XWPFParagraph imageParagraph = document.createParagraph();
                    imageParagraph.setAlignment(ParagraphAlignment.CENTER);
                    
                    XWPFRun imageRun = imageParagraph.createRun();
                    
                    // 读取图片
                    try (FileInputStream imageStream = new FileInputStream(diagramPath)) {
                        // 插入图片（调整尺寸）
                        imageRun.addPicture(imageStream,
                                XWPFDocument.PICTURE_TYPE_PNG,
                                diagramType + ".png",
                                org.apache.poi.util.Units.toEMU(450), // 宽度
                                org.apache.poi.util.Units.toEMU(300)  // 高度
                        );
                    }
                    
                    // 添加图注
                    XWPFParagraph captionParagraph = document.createParagraph();
                    captionParagraph.setAlignment(ParagraphAlignment.CENTER);
                    
                    XWPFRun captionRun = captionParagraph.createRun();
                    captionRun.setText(String.format("图%d %s", 
                            figureNumber++, 
                            getDiagramChineseName(diagramType)));
                    captionRun.setFontSize(10);
                    captionRun.setBold(true);
                    
                    // 添加图表说明
                    if (description != null && !description.isEmpty()) {
                        XWPFParagraph descParagraph = document.createParagraph();
                        XWPFRun descRun = descParagraph.createRun();
                        descRun.setText(description);
                        descRun.setFontSize(10);
                    }
                    
                    log.info("成功插入图表: {}", diagramType);
                    
                } catch (Exception e) {
                    log.error("插入图表失败: {}", diagramType, e);
                }
            } else {
                log.warn("图表文件不存在: {}", diagramPath);
            }
        }
        
        log.info("图表插入完成，共插入 {} 个图表", figureNumber - 1);
    }

    /**
     * 获取图表中文名称
     */
    private String getDiagramChineseName(String diagramType) {
        return switch (diagramType) {
            case "classDiagram" -> "类图";
            case "packageDependency" -> "包依赖图";
            case "sequenceDiagram" -> "时序图";
            case "layerArchitecture" -> "分层架构图";
            case "componentInteraction" -> "组件交互图";
            case "moduleRelation" -> "模块关系图";
            case "businessFlow" -> "业务流程图";
            case "stateMachine" -> "状态机图";
            case "designPatterns" -> "设计模式图";
            case "deploymentArchitecture" -> "部署架构图";
            case "monitoringArchitecture" -> "监控架构图";
            case "erDiagram" -> "ER图";
            default -> "系统图";
        };
    }

    /**
     * 生成包含图表的HTML预览
     */
    private String generateHtmlPreviewWithDiagrams(
            XWPFDocument document, 
            Map<String, String> availableDiagrams) {
        
        StringBuilder html = new StringBuilder();
        html.append("<!DOCTYPE html><html><head><meta charset='UTF-8'>");
        html.append("<style>");
        html.append("body { font-family: 'SimSun', serif; line-height: 1.8; max-width: 900px; margin: 0 auto; padding: 40px; background: #f5f5f5; }");
        html.append(".content { background: white; padding: 60px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }");
        html.append("h1 { text-align: center; font-size: 22px; font-weight: bold; margin: 30px 0; }");
        html.append("h2 { font-size: 18px; font-weight: bold; margin: 25px 0 15px 0; }");
        html.append("h3 { font-size: 16px; font-weight: bold; margin: 20px 0 10px 0; }");
        html.append("p { text-indent: 2em; margin: 10px 0; text-align: justify; line-height: 2.0; }");
        html.append(".center { text-align: center; text-indent: 0; }");
        html.append(".figure { margin: 30px 0; text-align: center; }");
        html.append(".figure img { max-width: 100%; height: auto; border: 1px solid #ddd; padding: 10px; background: white; }");
        html.append(".figure-caption { text-align: center; font-weight: bold; margin: 10px 0 5px 0; font-size: 12px; }");
        html.append(".figure-description { text-indent: 0; margin: 5px 20px; font-size: 11px; color: #666; text-align: left; }");
        html.append("</style></head><body><div class='content'>");

        int figureNumber = 1;
        
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            String text = paragraph.getText();
            if (text.isEmpty()) continue;

            String style = paragraph.getStyle();
            ParagraphAlignment alignment = paragraph.getAlignment();

            if ("Heading1".equals(style)) {
                html.append("<h1>").append(escapeHtml(text)).append("</h1>");
            } else if ("Heading2".equals(style)) {
                html.append("<h2>").append(escapeHtml(text)).append("</h2>");
            } else if ("Heading3".equals(style)) {
                html.append("<h3>").append(escapeHtml(text)).append("</h3>");
            } else {
                String className = alignment == ParagraphAlignment.CENTER ? " class='center'" : "";
                html.append("<p").append(className).append(">")
                    .append(escapeHtml(text))
                    .append("</p>");
            }
            
            // 检查是否需要在此段落后插入图表
            String lowercaseText = text.toLowerCase();
            for (Map.Entry<String, String> diagram : availableDiagrams.entrySet()) {
                if (shouldInsertDiagramAfterText(lowercaseText, diagram.getKey())) {
                    html.append(generateFigureHtml(diagram.getKey(), diagram.getValue(), figureNumber++));
                    availableDiagrams.remove(diagram.getKey()); // 避免重复插入
                    break;
                }
            }
        }

        html.append("</div></body></html>");
        return html.toString();
    }

    /**
     * 判断是否应在指定文本后插入图表
     */
    private boolean shouldInsertDiagramAfterText(String text, String diagramType) {
        return switch (diagramType) {
            case "layerArchitecture" -> text.contains("架构") || text.contains("分层");
            case "classDiagram" -> text.contains("类图") || text.contains("类结构");
            case "sequenceDiagram" -> text.contains("时序") || text.contains("调用");
            case "businessFlow" -> text.contains("流程");
            case "designPatterns" -> text.contains("设计模式");
            case "deploymentArchitecture" -> text.contains("部署");
            case "erDiagram" -> text.contains("数据库") || text.contains("er图");
            default -> false;
        };
    }

    /**
     * 生成图表HTML
     */
    private String generateFigureHtml(String diagramType, String diagramPath, int figureNumber) {
        StringBuilder html = new StringBuilder();
        html.append("<div class='figure'>");
        html.append(String.format("<img src='file:///%s' alt='%s' />", 
                diagramPath.replace("\\", "/"),
                getDiagramChineseName(diagramType)));
        html.append(String.format("<div class='figure-caption'>图%d %s</div>", 
                figureNumber, 
                getDiagramChineseName(diagramType)));
        html.append(String.format("<div class='figure-description'>%s</div>", 
                getFigureDescription(diagramType)));
        html.append("</div>");
        return html.toString();
    }

    /**
     * 获取图表描述
     */
    private String getFigureDescription(String diagramType) {
        return switch (diagramType) {
            case "layerArchitecture" -> "图中展示了系统的分层架构设计，各层职责明确，实现了高内聚低耦合。";
            case "classDiagram" -> "图中展示了系统的核心类结构，包括类之间的继承和依赖关系。";
            case "sequenceDiagram" -> "图中展示了系统的主要业务流程和组件间的交互时序。";
            case "businessFlow" -> "图中展示了系统的核心业务流程，包括各个处理步骤和分支判断。";
            case "designPatterns" -> "图中展示了系统中应用的设计模式，体现了良好的软件设计实践。";
            case "deploymentArchitecture" -> "图中展示了系统的部署架构，包括服务器、数据库、缓存等组件的部署方式。";
            case "erDiagram" -> "图中展示了系统的数据库ER模型，描述了实体、属性和实体间的关系。";
            default -> "该图展示了系统的相关设计内容。";
        };
    }

    private String saveThesisVersion(XWPFDocument document, String taskId, Integer version) 
            throws IOException {
        
        Path outputDir = Paths.get(workspaceBasePath, taskId, "output");
        Files.createDirectories(outputDir);
        
        String filename = String.format("thesis_v%d.docx", version);
        Path outputPath = outputDir.resolve(filename);
        
        try (FileOutputStream out = new FileOutputStream(outputPath.toFile())) {
            document.write(out);
        }
        
        return outputPath.toString();
    }

    private String generateHtmlPreview(XWPFDocument document) {
        StringBuilder html = new StringBuilder();
        html.append("<!DOCTYPE html><html><head><meta charset='UTF-8'>");
        html.append("<style>");
        html.append("body { font-family: 'SimSun', serif; line-height: 1.8; max-width: 800px; margin: 0 auto; padding: 40px; }");
        html.append("h1 { text-align: center; font-size: 22px; font-weight: bold; margin: 30px 0; }");
        html.append("h2 { font-size: 18px; font-weight: bold; margin: 25px 0 15px 0; }");
        html.append("h3 { font-size: 16px; font-weight: bold; margin: 20px 0 10px 0; }");
        html.append("p { text-indent: 2em; margin: 10px 0; text-align: justify; }");
        html.append(".center { text-align: center; text-indent: 0; }");
        html.append("</style></head><body>");

        for (XWPFParagraph paragraph : document.getParagraphs()) {
            String text = paragraph.getText();
            if (text.isEmpty()) continue;

            String style = paragraph.getStyle();
            ParagraphAlignment alignment = paragraph.getAlignment();

            if ("Heading1".equals(style)) {
                html.append("<h1>").append(escapeHtml(text)).append("</h1>");
            } else if ("Heading2".equals(style)) {
                html.append("<h2>").append(escapeHtml(text)).append("</h2>");
            } else if ("Heading3".equals(style)) {
                html.append("<h3>").append(escapeHtml(text)).append("</h3>");
            } else {
                String className = alignment == ParagraphAlignment.CENTER ? " class='center'" : "";
                html.append("<p").append(className).append(">")
                    .append(escapeHtml(text))
                    .append("</p>");
            }
        }

        html.append("</body></html>");
        return html.toString();
    }

    private XWPFParagraph findParagraphBySection(XWPFDocument document, String section) {
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            if (paragraph.getText().contains(section)) {
                return paragraph;
            }
        }
        return null;
    }

    private void replaceParagraphText(XWPFParagraph paragraph, String newText) {
        // 清除现有runs
        while (paragraph.getRuns().size() > 0) {
            paragraph.removeRun(0);
        }
        
        // 添加新文本
        XWPFRun run = paragraph.createRun();
        run.setText(newText);
        run.setFontSize(12);
    }

    private List<String> extractAllPlaceholders(String text) {
        List<String> placeholders = new ArrayList<>();
        int start = 0;
        
        while ((start = text.indexOf("{{", start)) != -1) {
            int end = text.indexOf("}}", start);
            if (end != -1) {
                placeholders.add(text.substring(start, end + 2));
                start = end + 2;
            } else {
                break;
            }
        }
        
        return placeholders;
    }

    private String escapeHtml(String text) {
        return text.replace("&", "&amp;")
                   .replace("<", "&lt;")
                   .replace(">", "&gt;")
                   .replace("\"", "&quot;");
    }
}

